<?php
/**
 * 文件缓存引擎
 *
 * @since 1.0
 * @package if
 * @subpackage module.cache
 */
class IFileCacheEngine extends IAbstractCacheEngine {
	private $settings;
	/**
	 * Enter description here...
	 *
	 * @var IFile
	 */
	private $dir;
	private $fileExt;
	private $securityString = "<?php exit(); ?>";
	
	function init(array $settings = null) {
		//取得配置
		if (!$settings) {
			$settings = array();
		}
		$_settings = o("@cache.file");
		if (is_array($_settings)) {
			$settings = array_merge($_settings, $settings);
		}
		$this->settings = $settings;
		
		//校验配置
		if (!isset($this->settings["dir"])) {
			$this->settings["dir"] = "./cache";
		}
		$this->dir = IApplication::singleton()->relativeFile($settings["dir"]);
		if (!$this->dir->exists()) {
			if (!@$this->dir->mkdirs()) {
				throw new ICacheException("cache dir '{$this->settings['dir']}' doesn't exist", 0x100067);
			}
		}
		$this->fileExt = o("@cache.file.file_ext");
	}
	
	function clear($expired = false) {
		$list = $this->dir->lists("*" . $this->fileExt, true);
		$ret = true;
		foreach ($list as $file) {
			if ($expired) {
				$data = substr($file->reader()->read(), strlen($this->securityString));
				$array = @unserialize($data);
				if (!is_array($array)) {
					if (!$file->delete()) {
						$ret = false;
					}
				}
				else {
					$entry = new ICacheEntry($array);
					$entry->setEngine($this);
					if ($entry->expired()) {
						if (!$file->delete()) {
							$ret = false;
						}
					}
				}
			}
			else {
				if (!$file->delete()) {
					$ret = false;
				}
			}
		}
		return $ret;
	}
	
	function delete($key) {
		$file = $this->file($key);
		if ($file->exists() && $file->isFile()) {
			return $file->delete();
		}
		return true;
	}
	
	function _entry($key) {
		$file = $this->file($key);
		if (!$file->exists()) {
			return null;
		}
		$data = substr($file->reader()->read(), strlen($this->securityString));
		$array = @unserialize($data);
		if (!is_array($array)) {
			$this->delete($key);
			return null;
		}
		$entry = new ICacheEntry($array);
		$entry->setEngine($this);
		if ($entry->expired()) {
			$this->delete($key);
			return null;
		}
		return $entry;
	}
	
	function _writeEntry(ICacheEntry $entry) {
		$array = $entry->asArray();
		$data = serialize($array);
		$writer = $this->file($entry->key(), true)->writer();
		$ret = $writer->write($this->securityString . $data);
		$writer->close();
		return $ret>0;
	}
	
	/**
	 * 根据key查找文件，并创建IFile对象
	 * 
	 * 从1.0.3开始，缓存文件的文件名前面加入~符号
	 *
	 * @param string $key
	 * @param boolean $create 如果不存在是否新建
	 * @return IFile
	 * @since 1.0
	 */
	private function file($key, $create = false) {
		$_key = md5($key);
		$_dir = $this->dir->absPath() . "/" . $_key{0} . $_key{1} . "/" . $_key{2} . $_key{3};
		if (!is_dir($_dir) && $create) {
			$dirFile = new IFile($_dir);
			$dirFile->mkdirs();
		}
		$file = new IFile($_dir . "/" . "~" . $_key . $this->fileExt);
		return $file;
	}
}


?>